Skip to content

feat(chat): add compact tool UI mode for executed tool blocks (#322) - #327

Open
proyectoauraorg wants to merge 5 commits into
Zoo-Code-Org:mainfrom
proyectoauraorg:feat/322-compact-tool-ui
Open

feat(chat): add compact tool UI mode for executed tool blocks (#322)#327
proyectoauraorg wants to merge 5 commits into
Zoo-Code-Org:mainfrom
proyectoauraorg:feat/322-compact-tool-ui

Conversation

@proyectoauraorg

@proyectoauraorg proyectoauraorg commented May 25, 2026

Copy link
Copy Markdown
Contributor

Related GitHub Issue

Closes #322

Description

Adds an opt-in Compact tool display setting (compactToolUI, off by default) that collapses executed (say) tool blocks in the chat history to a single, clickable line — hiding long descriptions and JSON payloads until the user clicks to expand. This addresses the issue's complaint: verbose tool blocks push the actual conversation out of view and make history tedious to scroll.

Scope

Compaction applies to executed file-operation tool rows — the saycase "tool" branch in ChatRow. The use_mcp_server branch (line ~1623) is intentionally left untouched in this PR. Per review discussion, MCP history compaction will be handled in a separate follow-up issue/PR, since MCP blocks have a different shape (server/tool/arguments/response) and deserve their own compact layout.

Design decision: approval prompts (ask tool messages) are never compacted — only completed/history (say) tool rows are — so users always see the parameters they are approving before acting.

How it works

  • New global boolean compactToolUI in globalSettingsSchema + ExtensionState, persisted via ClineProvider.getState() / getStateToPostToWebview() so it survives reloads.
  • Toggle in Context Management settings (compact-tool-ui-checkbox).
  • In ChatRow, the say tool branch renders a single line (chevron + 🔧 + Tool: <name/path>) when compactToolUI && !isExpanded; clicking the row (a semantic <button> with aria-expanded={false}) toggles expansion and falls through to the normal full render.
  • New i18n keys (settings:contextManagement.compactToolUI.*, chat:compactTool.*) added across all 18 locales.

Testing

  • ContextManagementSettings.spec.tsx: toggle renders + fires setCachedStateField("compactToolUI", …).
  • ChatRow.compact-tool.spec.tsx: mounts ChatRowContent with compactToolUI=true and a say tool message; asserts the compact row renders, that clicking it calls onToggleExpand(message.ts), and that the button carries aria-expanded="false".
  • tsc -b (webview) and tsc --noEmit (src) clean; eslint clean; find-missing-translations reports complete parity.

@coderabbitai

coderabbitai Bot commented May 25, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

(Note: the hidden artifact above is machine-parsed; do not edit.)
Walkthrough

Adds an optional compactToolUI setting and implements a compact single-line rendering for executed "say" tool blocks in chat, wired through provider/extension state, SettingsView/ContextManagementSettings, ChatRow rendering, unit tests, and translations.

Changes

Compact Tool UI Feature

Layer / File(s) Summary
Schema, types, provider and context state
packages/types/src/global-settings.ts, packages/types/src/vscode-extension-host.ts, webview-ui/src/context/ExtensionStateContext.tsx, src/core/webview/ClineProvider.ts
Adds compactToolUI to globalSettingsSchema and ExtensionState, initializes compactToolUI: false in ExtensionStateContext provider, and wires compactToolUI into ClineProvider state posted to the webview.
Settings UI and state wiring
webview-ui/src/components/settings/ContextManagementSettings.tsx, webview-ui/src/components/settings/SettingsView.tsx
ContextManagementSettings accepts a compactToolUI prop, renders a checkbox that calls setCachedStateField("compactToolUI", ...); SettingsView reads compactToolUI from cachedState, includes it in update payloads, and forwards it to ContextManagementSettings.
Chat row compact rendering
webview-ui/src/components/chat/ChatRow.tsx
ChatRow imports ChevronRight, reads compactToolUI from extension state, and returns an early single-line clickable summary (chevron + tool label) for executed say tool rows when compact mode is enabled and the row is collapsed.
Tests and internationalization
webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx, webview-ui/src/i18n/locales/*/chat.json, webview-ui/src/i18n/locales/*/settings.json
Adds unit tests verifying the compact-tool checkbox renders and toggles cached state; adds compactTool chat strings and contextManagement.compactToolUI settings translations across many locale files.

Sequence Diagram

sequenceDiagram
  participant User
  participant SettingsView
  participant ClineProvider
  participant ExtensionStateContext
  participant ChatRow
  User->>SettingsView: toggle compactToolUI
  SettingsView->>ClineProvider: set cached compactToolUI
  ClineProvider->>ExtensionStateContext: post state including compactToolUI
  ExtensionStateContext->>ChatRow: provide compactToolUI via context
  ChatRow->>User: render compact single-line summary when enabled
  User->>ChatRow: click to expand
  ChatRow->>User: render full tool UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • taltas
  • navedmerchant
  • hannesrudolph
  • JamesRobert20

Poem

🐰 I nibble code and tidy threads,
A chevron tucks away long spreads.
One slim line, a click to show—
Quiet chat, then details grow.
Hop, reveal, compact and neat.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding a compact tool UI mode for executed tool blocks in chat.
Linked Issues check ✅ Passed The implementation fully addresses issue #322: adds opt-in global setting, collapses executed (say) tool blocks to single line, keeps approval (ask) prompts expanded, and provides expansion interaction.
Out of Scope Changes check ✅ Passed All changes are directly scoped to the compact tool UI feature: schema/state additions, settings UI toggle, chat row rendering logic, internationalization keys, and related tests.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The PR description comprehensively covers the linked issue, implementation details, scope, design decisions, and testing approach with clear explanations of the feature and its limitations.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
webview-ui/src/components/settings/SettingsView.tsx (1)

366-426: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

compactToolUI is not persisted on Save.

Line 366 builds updatedSettings, but compactToolUI is missing, so the new toggle won’t survive save/reload.

💡 Suggested fix
 				updatedSettings: {
 					language,
@@
 					showRooIgnoredFiles: showRooIgnoredFiles ?? true,
+					compactToolUI: compactToolUI ?? false,
 					enableSubfolderRules: enableSubfolderRules ?? false,

As per coding guidelines, “For SettingsView, preserve the cached-state pattern: inputs should operate on local cachedState until the user saves…”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview-ui/src/components/settings/SettingsView.tsx` around lines 366 - 426,
The updatedSettings object built in SettingsView omits compactToolUI so the
toggle in cachedState never gets persisted; add compactToolUI: compactToolUI ??
/* default value or cachedState.compactToolUI */ to the updatedSettings payload
(keeping the same null/undefined handling pattern as other fields) so the local
cachedState value for compactToolUI is saved on Save and survives reload.
🧹 Nitpick comments (1)
webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx (1)

154-169: ⚡ Quick win

Add one SettingsView save-path regression test for compactToolUI.

These tests validate checkbox wiring, but not persistence through updateSettings. A SettingsView test asserting vscode.postMessage({ type: "updateSettings", updatedSettings: { compactToolUI: ... } }) would catch the current integration bug.

As per coding guidelines, “Prefer local webview-ui tests for React/webview behavior such as component rendering, local state, hooks, form dirty-state, validation, or prop wiring.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx`
around lines 154 - 169, Tests for ContextManagementSettings only check checkbox
wiring but do not assert that toggling persists via SettingsView's
updateSettings message; add a new test in the SettingsView test suite that
mounts the SettingsView (or renders the component that wires
ContextManagementSettings into the webview messaging layer), simulates toggling
the compactToolUI checkbox, and asserts that vscode.postMessage was called with
{ type: "updateSettings", updatedSettings: { compactToolUI: true/false } };
locate the integration wiring around SettingsView (where
ContextManagementSettings is used and updateSettings is invoked) and mock/spy on
vscode.postMessage to validate the exact payload for compactToolUI.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webview-ui/src/components/chat/ChatRow.tsx`:
- Around line 1423-1434: Replace the clickable div used for compact-row
expansion with a semantic <button type="button"> so keyboard users can activate
it; move the onClick={handleToggleExpand} to the button, keep the className and
children (ChevronRight, PocketKnife, span), add an aria-expanded attribute bound
to the component's expanded state (e.g., aria-expanded={isExpanded} or the
appropriate state variable) and preserve data-testid="compact-tool-row"; ensure
the button does not submit forms (type="button") and that any focus/hover styles
remain intact so keyboard users can tab and press Enter/Space to toggle the
compact tool row.

---

Outside diff comments:
In `@webview-ui/src/components/settings/SettingsView.tsx`:
- Around line 366-426: The updatedSettings object built in SettingsView omits
compactToolUI so the toggle in cachedState never gets persisted; add
compactToolUI: compactToolUI ?? /* default value or cachedState.compactToolUI */
to the updatedSettings payload (keeping the same null/undefined handling pattern
as other fields) so the local cachedState value for compactToolUI is saved on
Save and survives reload.

---

Nitpick comments:
In
`@webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx`:
- Around line 154-169: Tests for ContextManagementSettings only check checkbox
wiring but do not assert that toggling persists via SettingsView's
updateSettings message; add a new test in the SettingsView test suite that
mounts the SettingsView (or renders the component that wires
ContextManagementSettings into the webview messaging layer), simulates toggling
the compactToolUI checkbox, and asserts that vscode.postMessage was called with
{ type: "updateSettings", updatedSettings: { compactToolUI: true/false } };
locate the integration wiring around SettingsView (where
ContextManagementSettings is used and updateSettings is invoked) and mock/spy on
vscode.postMessage to validate the exact payload for compactToolUI.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 24ee0f03-114c-47e8-8ef6-5328ecd340a5

📥 Commits

Reviewing files that changed from the base of the PR and between 9d022d4 and d5ae590.

📒 Files selected for processing (43)
  • packages/types/src/global-settings.ts
  • packages/types/src/vscode-extension-host.ts
  • webview-ui/src/components/chat/ChatRow.tsx
  • webview-ui/src/components/settings/ContextManagementSettings.tsx
  • webview-ui/src/components/settings/SettingsView.tsx
  • webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx
  • webview-ui/src/context/ExtensionStateContext.tsx
  • webview-ui/src/i18n/locales/ca/chat.json
  • webview-ui/src/i18n/locales/ca/settings.json
  • webview-ui/src/i18n/locales/de/chat.json
  • webview-ui/src/i18n/locales/de/settings.json
  • webview-ui/src/i18n/locales/en/chat.json
  • webview-ui/src/i18n/locales/en/settings.json
  • webview-ui/src/i18n/locales/es/chat.json
  • webview-ui/src/i18n/locales/es/settings.json
  • webview-ui/src/i18n/locales/fr/chat.json
  • webview-ui/src/i18n/locales/fr/settings.json
  • webview-ui/src/i18n/locales/hi/chat.json
  • webview-ui/src/i18n/locales/hi/settings.json
  • webview-ui/src/i18n/locales/id/chat.json
  • webview-ui/src/i18n/locales/id/settings.json
  • webview-ui/src/i18n/locales/it/chat.json
  • webview-ui/src/i18n/locales/it/settings.json
  • webview-ui/src/i18n/locales/ja/chat.json
  • webview-ui/src/i18n/locales/ja/settings.json
  • webview-ui/src/i18n/locales/ko/chat.json
  • webview-ui/src/i18n/locales/ko/settings.json
  • webview-ui/src/i18n/locales/nl/chat.json
  • webview-ui/src/i18n/locales/nl/settings.json
  • webview-ui/src/i18n/locales/pl/chat.json
  • webview-ui/src/i18n/locales/pl/settings.json
  • webview-ui/src/i18n/locales/pt-BR/chat.json
  • webview-ui/src/i18n/locales/pt-BR/settings.json
  • webview-ui/src/i18n/locales/ru/chat.json
  • webview-ui/src/i18n/locales/ru/settings.json
  • webview-ui/src/i18n/locales/tr/chat.json
  • webview-ui/src/i18n/locales/tr/settings.json
  • webview-ui/src/i18n/locales/vi/chat.json
  • webview-ui/src/i18n/locales/vi/settings.json
  • webview-ui/src/i18n/locales/zh-CN/chat.json
  • webview-ui/src/i18n/locales/zh-CN/settings.json
  • webview-ui/src/i18n/locales/zh-TW/chat.json
  • webview-ui/src/i18n/locales/zh-TW/settings.json

Comment thread webview-ui/src/components/chat/ChatRow.tsx Outdated
@codecov

codecov Bot commented May 25, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.38710% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/core/webview/ClineProvider.ts 66.66% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

…de-Org#322)

Adds an opt-in global setting (compactToolUI, off by default) that collapses
executed (say) tool blocks in the chat history to a single clickable line,
hiding verbose descriptions and JSON payloads until the user expands them.

Approval prompts (ask) are never compacted, so users always see the parameters
they are approving. Toggle lives in Context Management settings; new i18n keys
added across all 18 locales. Closes Zoo-Code-Org#322.
@proyectoauraorg
proyectoauraorg force-pushed the feat/322-compact-tool-ui branch from d5ae590 to fd5ecdd Compare May 26, 2026 04:50

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@webview-ui/src/components/settings/SettingsView.tsx`:
- Around line 838-839: The save payload omits the compactToolUI field so
toggling it is not persisted; update the handleSubmit function to include
compactToolUI (the same state/prop used when rendering) in the updatedSettings
object before sending/saving, e.g. add compactToolUI: compactToolUI (or
compactToolUI ?? false) to updatedSettings so the toggle is persisted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 932d5575-a57a-49f6-b31c-0dc5f5e739cc

📥 Commits

Reviewing files that changed from the base of the PR and between d5ae590 and fd5ecdd.

📒 Files selected for processing (43)
  • packages/types/src/global-settings.ts
  • packages/types/src/vscode-extension-host.ts
  • webview-ui/src/components/chat/ChatRow.tsx
  • webview-ui/src/components/settings/ContextManagementSettings.tsx
  • webview-ui/src/components/settings/SettingsView.tsx
  • webview-ui/src/components/settings/__tests__/ContextManagementSettings.spec.tsx
  • webview-ui/src/context/ExtensionStateContext.tsx
  • webview-ui/src/i18n/locales/ca/chat.json
  • webview-ui/src/i18n/locales/ca/settings.json
  • webview-ui/src/i18n/locales/de/chat.json
  • webview-ui/src/i18n/locales/de/settings.json
  • webview-ui/src/i18n/locales/en/chat.json
  • webview-ui/src/i18n/locales/en/settings.json
  • webview-ui/src/i18n/locales/es/chat.json
  • webview-ui/src/i18n/locales/es/settings.json
  • webview-ui/src/i18n/locales/fr/chat.json
  • webview-ui/src/i18n/locales/fr/settings.json
  • webview-ui/src/i18n/locales/hi/chat.json
  • webview-ui/src/i18n/locales/hi/settings.json
  • webview-ui/src/i18n/locales/id/chat.json
  • webview-ui/src/i18n/locales/id/settings.json
  • webview-ui/src/i18n/locales/it/chat.json
  • webview-ui/src/i18n/locales/it/settings.json
  • webview-ui/src/i18n/locales/ja/chat.json
  • webview-ui/src/i18n/locales/ja/settings.json
  • webview-ui/src/i18n/locales/ko/chat.json
  • webview-ui/src/i18n/locales/ko/settings.json
  • webview-ui/src/i18n/locales/nl/chat.json
  • webview-ui/src/i18n/locales/nl/settings.json
  • webview-ui/src/i18n/locales/pl/chat.json
  • webview-ui/src/i18n/locales/pl/settings.json
  • webview-ui/src/i18n/locales/pt-BR/chat.json
  • webview-ui/src/i18n/locales/pt-BR/settings.json
  • webview-ui/src/i18n/locales/ru/chat.json
  • webview-ui/src/i18n/locales/ru/settings.json
  • webview-ui/src/i18n/locales/tr/chat.json
  • webview-ui/src/i18n/locales/tr/settings.json
  • webview-ui/src/i18n/locales/vi/chat.json
  • webview-ui/src/i18n/locales/vi/settings.json
  • webview-ui/src/i18n/locales/zh-CN/chat.json
  • webview-ui/src/i18n/locales/zh-CN/settings.json
  • webview-ui/src/i18n/locales/zh-TW/chat.json
  • webview-ui/src/i18n/locales/zh-TW/settings.json
✅ Files skipped from review due to trivial changes (21)
  • webview-ui/src/i18n/locales/hi/chat.json
  • webview-ui/src/i18n/locales/de/settings.json
  • webview-ui/src/i18n/locales/es/chat.json
  • webview-ui/src/i18n/locales/nl/settings.json
  • webview-ui/src/i18n/locales/en/chat.json
  • webview-ui/src/i18n/locales/hi/settings.json
  • webview-ui/src/i18n/locales/vi/settings.json
  • webview-ui/src/i18n/locales/ja/settings.json
  • webview-ui/src/i18n/locales/fr/settings.json
  • webview-ui/src/i18n/locales/tr/settings.json
  • webview-ui/src/i18n/locales/zh-TW/chat.json
  • webview-ui/src/i18n/locales/en/settings.json
  • webview-ui/src/i18n/locales/ru/settings.json
  • webview-ui/src/i18n/locales/ru/chat.json
  • webview-ui/src/i18n/locales/ko/chat.json
  • webview-ui/src/i18n/locales/ko/settings.json
  • webview-ui/src/i18n/locales/ca/settings.json
  • webview-ui/src/i18n/locales/fr/chat.json
  • webview-ui/src/i18n/locales/zh-CN/settings.json
  • webview-ui/src/i18n/locales/ja/chat.json
  • webview-ui/src/i18n/locales/pt-BR/settings.json

Comment thread webview-ui/src/components/settings/SettingsView.tsx
- Add compactToolUI to updatedSettings in handleSubmit so the preference persists when saving
- Change <div onClick> to <button> for keyboard accessibility and proper semantics

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
webview-ui/src/components/chat/ChatRow.tsx (1)

1423-1434: ⚡ Quick win

Add aria-expanded attribute for screen reader support.

The button correctly uses semantic HTML and supports keyboard interaction, but adding aria-expanded={isExpanded} would help screen readers announce whether the compact tool row is currently expanded or collapsed.

♿ Proposed accessibility enhancement
 							<button
 								type="button"
 								onClick={handleToggleExpand}
+								aria-expanded={isExpanded}
 								className="flex items-center gap-2 py-0.5 cursor-pointer text-vscode-descriptionForeground hover:text-vscode-foreground bg-transparent border-none text-inherit w-full text-left"
 								data-testid="compact-tool-row"
 								title={t("chat:compactTool.expandHint")}>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@webview-ui/src/components/chat/ChatRow.tsx` around lines 1423 - 1434, The
compact tool toggle button in ChatRow.tsx lacks an aria-expanded attribute;
update the button rendered alongside <ChevronRight /> and <PocketKnife /> (the
element that calls handleToggleExpand and uses compactLabel) to include
aria-expanded={isExpanded} so screen readers can detect expanded/collapsed
state, keeping the existing props like data-testid and title unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@webview-ui/src/components/chat/ChatRow.tsx`:
- Around line 1423-1434: The compact tool toggle button in ChatRow.tsx lacks an
aria-expanded attribute; update the button rendered alongside <ChevronRight />
and <PocketKnife /> (the element that calls handleToggleExpand and uses
compactLabel) to include aria-expanded={isExpanded} so screen readers can detect
expanded/collapsed state, keeping the existing props like data-testid and title
unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0afb8605-c6b1-4de5-8573-86a528b7da68

📥 Commits

Reviewing files that changed from the base of the PR and between fd5ecdd and d356ab6.

📒 Files selected for processing (2)
  • webview-ui/src/components/chat/ChatRow.tsx
  • webview-ui/src/components/settings/SettingsView.tsx

Comment thread webview-ui/src/context/ExtensionStateContext.tsx
Comment thread webview-ui/src/components/chat/ChatRow.tsx
getState() read compactToolUI from storage but never returned it, so
getStateToPostToWebview() never sent the persisted value to the webview and the
`false` default always won on reload. Wire it through both getState() returns
following the showRooIgnoredFiles pattern. Addresses PR Zoo-Code-Org#327 review (edelauna).
@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

Thanks for the review @edelauna!

  1. Reload bug fixedcompactToolUI is now wired through both getState() returns (following the showRooIgnoredFiles pattern), so the persisted value reaches the webview instead of the false default always winning on reload.
  2. On the use_mcp_server branch: it renders as an ask (approval prompt), and the feature intentionally never compacts approvals so you can always see what you're authorizing before acting. Compacting MCP rows only makes sense once they're answered/in history — happy to do that as a follow-up if you'd like, otherwise I'll tighten the PR description to scope it to executed file-op tool blocks. Which do you prefer? 🦓

@edelauna edelauna left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok - lets just update the PR description, we can handle MCP history compaction in another issue/pr.

Had some minor questions.

onClick={handleToggleExpand}
className="flex items-center gap-2 py-0.5 cursor-pointer text-vscode-descriptionForeground hover:text-vscode-foreground bg-transparent border-none text-inherit w-full text-left"
data-testid="compact-tool-row"
title={t("chat:compactTool.expandHint")}>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding aria-expanded={false} here round out the a11y fix? Since this button only renders in the collapsed state, the value is always false, but it signals to screen readers that this is an expandable control.

Suggested change
title={t("chat:compactTool.expandHint")}>
title={t("chat:compactTool.expandHint")}
aria-expanded={false}>

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call — added aria-expanded={false} on the compact toggle button. Since it only renders in the collapsed state the value is always false, so it just signals to screen readers that this is an expandable control. It's on the <button> at ChatRow.tsx:1426.

await waitFor(() => {
expect(setCachedStateField).toHaveBeenCalledWith("compactToolUI", true)
})
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These cover the settings toggle nicely. Would it be worth also adding a test that mounts ChatRowContent with compactToolUI=true and a say tool message, to verify the compact row renders (and that clicking it calls onToggleExpand)? That would give a regression guard on the actual chat-side behaviour.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — added webview-ui/src/components/chat/__tests__/ChatRow.compact-tool.spec.tsx. It mounts ChatRowContent with compactToolUI=true and a say tool message and asserts: (1) the compact row renders, (2) clicking it calls onToggleExpand(message.ts), and (3) the button carries aria-expanded="false". Good regression guard — thanks for the nudge.

@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

Conflicts resolved and branch rebased on latest main. CI is passing. Ready for re-review. 🙏

Addresses CodeRabbit review nitpick: add aria-expanded={isExpanded}
to the compact tool row button for screen reader support.

Refs: PR Zoo-Code-Org#327 review feedback
@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

Thanks for the review @edelauna! I've addressed the feedback:

Changes made:

  1. Accessibility fix: Added aria-expanded={isExpanded} to the compact tool toggle button in ChatRow.tsx (addressing CodeRabbit's nitpick about screen reader support

Regarding your comments:

  • PR description: Will update to clarify that MCP history compaction is out of scope for this PR and should be handled in a separate issue/PR
  • MCP history compaction: Agreed — I'll open a separate issue to track this as a follow-up enhancement

The CI checks should pick up the new commit shortly. Let me know if there are any other questions or changes needed!
EOF
)

…dd ChatRow compact tool tests

- Change aria-expanded={isExpanded} to aria-expanded={false} per edelauna review
  (button only renders when !isExpanded, so value is always false)
- Add ChatRow.compact-tool.spec.tsx with 3 tests:
  1. Renders compact row when compactToolUI=true and not expanded
  2. Calls onToggleExpand when compact row is clicked
  3. Has aria-expanded=false on the compact button

Addresses review feedback on PR Zoo-Code-Org#327
@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

Updated per your review @edelauna:

  1. aria-expanded: Changed to aria-expanded={false} as you suggested — since the button only renders in the collapsed state, the value is always false but signals to screen readers this is an expandable control.

  2. ChatRow compact tool test: Added ChatRow.compact-tool.spec.tsx with 3 tests:

    • Verifies compact row renders when compactToolUI=true and not expanded
    • Verifies clicking the compact row calls onToggleExpand
    • Verifies aria-expanded=false is present on the button

All tests pass. Let me know if you'd like any further changes!

@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

@edelauna addressed your notes:

  • PR description updated — clarified the scope (only the saycase "tool" file-op branch is compacted; use_mcp_server is intentionally untouched) and noted MCP history compaction is deferred to a separate follow-up issue/PR, as agreed.
  • aria-expanded={false} added on the compact toggle button (ChatRow.tsx:1426).
  • New ChatRow.compact-tool.spec.tsx mounts ChatRowContent with compactToolUI=true + a say tool message and asserts the compact row renders, click calls onToggleExpand, and the button carries aria-expanded="false".

Persistence across reloads is wired through ClineProvider.getState() / getStateToPostToWebview(). CI is green. Re-requesting review when you have a moment 🙏

@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

@edelauna — friendly nudge for a re-review when you have a moment 🙏. Everything from the last round is in:

  • aria-expanded={false} on the compact toggle, and it's now a semantic <button> (keyboard-accessible), covering the a11y notes.
  • compactToolUI is persisted end-to-end — it's included in ClineProvider.getStateToPostToWebview() / getState() and in the handleSubmit save payload, so it survives reloads (the gap you and CodeRabbit flagged).
  • Scope clarified in the description: only the saycase "tool" file-op branch is compacted; use_mcp_server is intentionally untouched, with MCP history compaction deferred to a follow-up.
  • Added ChatRow.compact-tool.spec.tsx covering render + toggle + aria-expanded.

Branch is MERGEABLE. Thanks!

@proyectoauraorg

Copy link
Copy Markdown
Contributor Author

@edelauna — friendly nudge for re-review 🙏

All feedback from the last round has been addressed:

  • aria-expanded={false} on compact toggle (semantic <button>, keyboard-accessible)
  • compactToolUI persisted end-to-end via ClineProvider.getState() / getStateToPostToWebview() / handleSubmit save payload
  • ✅ Scope clarified: only saycase "tool" file-op branch compacted; MCP intentionally untouched (deferred to follow-up)
  • ✅ New ChatRow.compact-tool.spec.tsx covering render + toggle + aria-expanded
  • ✅ Branch is MERGEABLE, CI green

Let me know if you need any further changes!

edelauna
edelauna previously approved these changes Jun 2, 2026

@edelauna edelauna left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good - I created a follow up issue for some non blocking feedback: #455

Comment on lines +235 to +250
<SearchableSetting
settingId="context-compact-tool-ui"
section="contextManagement"
label={t("settings:contextManagement.compactToolUI.label")}>
<VSCodeCheckbox
checked={compactToolUI}
onChange={(e: any) => setCachedStateField("compactToolUI", e.target.checked)}
data-testid="compact-tool-ui-checkbox">
<label className="block font-medium mb-1">
{t("settings:contextManagement.compactToolUI.label")}
</label>
</VSCodeCheckbox>
<div className="text-vscode-descriptionForeground text-sm mt-1 mb-3">
{t("settings:contextManagement.compactToolUI.description")}
</div>
</SearchableSetting>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this live in UISettings.tsx instead? compactToolUI controls how chat rows render (display preference), while this section manages what data gets sent to the model's context window (maxOpenTabsContext, maxWorkspaceFiles). UISettings already has the analogous reasoningBlockCollapsed (collapse thinking blocks in chat).

Comment on lines +80 to +108
describe("ChatRow - compact tool UI", () => {
beforeEach(() => {
vi.clearAllMocks()
mockOnToggleExpand.mockClear()
})

it("renders the compact row when compactToolUI is true and not expanded", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)

expect(screen.getByTestId("compact-tool-row")).toBeInTheDocument()
})

it("calls onToggleExpand when the compact row is clicked", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)

fireEvent.click(screen.getByTestId("compact-tool-row"))

expect(mockOnToggleExpand).toHaveBeenCalledWith(message.ts)
})

it("has aria-expanded=false on the compact button", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)

expect(screen.getByTestId("compact-tool-row")).toHaveAttribute("aria-expanded", "false")
})
})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These cover the happy path well. Worth adding negative-path cases for isExpanded=true and compactToolUI=false? Both branches guard the compact render — if either condition is accidentally dropped, no test would catch it.

Suggested change
describe("ChatRow - compact tool UI", () => {
beforeEach(() => {
vi.clearAllMocks()
mockOnToggleExpand.mockClear()
})
it("renders the compact row when compactToolUI is true and not expanded", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)
expect(screen.getByTestId("compact-tool-row")).toBeInTheDocument()
})
it("calls onToggleExpand when the compact row is clicked", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)
fireEvent.click(screen.getByTestId("compact-tool-row"))
expect(mockOnToggleExpand).toHaveBeenCalledWith(message.ts)
})
it("has aria-expanded=false on the compact button", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)
expect(screen.getByTestId("compact-tool-row")).toHaveAttribute("aria-expanded", "false")
})
})
describe("ChatRow - compact tool UI", () => {
beforeEach(() => {
vi.clearAllMocks()
mockOnToggleExpand.mockClear()
})
it("renders the compact row when compactToolUI is true and not expanded", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)
expect(screen.getByTestId("compact-tool-row")).toBeInTheDocument()
})
it("does NOT render compact row when isExpanded is true", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, true)
expect(screen.queryByTestId("compact-tool-row")).not.toBeInTheDocument()
})
it("calls onToggleExpand when the compact row is clicked", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)
fireEvent.click(screen.getByTestId("compact-tool-row"))
expect(mockOnToggleExpand).toHaveBeenCalledWith(message.ts)
})
it("has aria-expanded=false on the compact button", () => {
const message = createSayToolMessage({ tool: "readFile", path: "src/file.ts" })
renderChatRow(message, false)
expect(screen.getByTestId("compact-tool-row")).toHaveAttribute("aria-expanded", "false")
})
})

@edelauna
edelauna dismissed their stale review June 2, 2026 22:30

Want to test more actually.

@DScoNOIZ

DScoNOIZ commented Jun 9, 2026

Copy link
Copy Markdown

@proyectoauraorg You have no idea how grateful I am to you! It was worth researching pulls. This is probably the most useful modification you've made.
I'll pull this into my local repository immediately.

I was going to implement all of this from scratch.
But I think there should be three modes.
To execute commands, MCP servers.
And file operations.
There should be the ability to flexibly configure these three things.

And there should be three modes. 1) Normal, like now.
2) Folded, that is, minimized, in a thin line like Pochi, with the ability to unfold.

  1. And completely hidden, when we don't even see what tools are being executed. That is, they completely disappear from the chat, and the agent executes them completely in the background, invisible to us.

Moreover, it should be flexibly configured for each type (MCP, terminal commands, file operations.

I want to implement all this in my own place.
Thank you so much. Now I have something to start with!

@edelauna edelauna left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@proyectoauraorg can you add some screenshots for how the compaction works? I'm not able to reproduce it, and see a difference between before or after.

@github-actions github-actions Bot added has-conflicts PR has merge conflicts with the base branch awaiting-author PR is waiting for the author to address requested changes and removed has-conflicts PR has merge conflicts with the base branch awaiting-author PR is waiting for the author to address requested changes labels Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

has-conflicts PR has merge conflicts with the base branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ENHANCEMENT] Add a strict "Compact Mode" for tool usage UI to save vertical space

3 participants